package cn.code4java.springbok.utils.excel;

import cn.code4java.springbok.utils.StringUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @ClassName ExcelUtils
 * @Description: TODO
 * @Author fengwensheng
 * @Date 2024/7/6
 * @Version V2.0.0
 **/
@Slf4j
public class ExcelUtils<T> {

    private Class<T> clazz;
    /**
     * 导出文件路径
     */
    public static final String EXPORT_PATH = "D:\\excel\\";

    /**
     * 抽象处理器
     */
    private ExcelImportHandler<T> excelImportHandler;
    private ExcelExportHandler<T> excelExportHandler;

    public ExcelUtils(Class<T> clazz, ExcelImportHandler<T> excelImportHandler) {
        this.clazz = clazz;
        this.excelImportHandler = excelImportHandler;
    }

    public ExcelUtils(Class<T> clazz, ExcelExportHandler<T> excelExportHandler) {
        this.clazz = clazz;
        this.excelExportHandler = excelExportHandler;
    }

    public ExcelUtils(Class<T> clazz) {
        this.clazz = clazz;
    }

    /**
     * 分段导入excel，默认导入第一个sheet
     *
     * @param inputStream
     * @throws IOException
     */
    public void importExcelSegment(InputStream inputStream) throws IOException, ClassNotFoundException {
        this.importExcelSegment(inputStream, null);
    }

    /**
     * 分段导入excel，指定导入的sheet
     *
     * @param inputStream
     * @param sheetName
     * @throws IOException
     */
    public void importExcelSegment(InputStream inputStream, String sheetName) throws IOException, ClassNotFoundException {
        if (this.excelImportHandler == null) {
            throw new ClassNotFoundException("ExcelImportAbstractHandler类不存在，请通过构造函数写入excelImportAbstractHandler参数");
        }
        ReadSheet readSheet;
        try {
            ExcelReader build = EasyExcel.read(inputStream).build();
            if (StringUtils.isNotBlank(sheetName)) {
                readSheet = EasyExcel.readSheet(sheetName).head(this.clazz).registerReadListener(new ExcelListener<T>(this.excelImportHandler)).build();
            } else {
                readSheet = EasyExcel.readSheet().head(this.clazz).registerReadListener(new ExcelListener<T>(this.excelImportHandler)).build();
            }
            build.read(readSheet);
        } finally {
            inputStream.close();
        }
    }

    /**
     * 分段导入excel，默认导入第一个sheet
     *
     * @param pathName
     * @throws IOException
     */
    public void importExcelSegment(String pathName) throws IOException, ClassNotFoundException {
        this.importExcelSegment(pathName, null);
    }

    /**
     * 分段导入excel，指定导入的sheet
     *
     * @param pathName
     * @param sheetName
     * @throws IOException
     */
    public void importExcelSegment(String pathName, String sheetName) throws IOException, ClassNotFoundException {
        InputStream inputStream = new FileInputStream(pathName);
        this.importExcelSegment(inputStream, sheetName);
    }

    /**
     * 导入，大数据量读取不推荐使用
     *
     * @param pathName
     * @param sheetName
     * @return
     */
    public List<T> importExcel(String pathName, String sheetName) throws IOException {
        InputStream inputStream = new FileInputStream(pathName);
        return this.importExcel(inputStream, sheetName);
    }

    /**
     * 导入，大数据量读取不推荐使用
     *
     * @param inputStream
     * @param sheetName
     * @return
     */
    public List<T> importExcel(InputStream inputStream, String sheetName) throws IOException {
        try {
            List<T> list;
            if (StringUtils.isNotBlank(sheetName)) {
                list = EasyExcel.read(inputStream).head(this.clazz).sheet().doReadSync();
            } else {
                list = EasyExcel.read(inputStream).head(this.clazz).sheet().doReadSync();
            }
            return list;
        } finally {
            inputStream.close();
        }
    }

    /**
     * 分段导出，大数据量写入时建议使用分段查询分段写入
     *
     * @param fileName
     * @param sheetName
     * @return
     */
    public String exportExcelSegment(String fileName, String sheetName) throws ClassNotFoundException {
        if (this.excelExportHandler == null) {
            throw new ClassNotFoundException("ExcelExportHandler类不存在，请通过构造函数写入excelExportHandler参数");
        }
        try (ExcelWriter excelWriter = EasyExcel.write(EXPORT_PATH + fileName, this.clazz).build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
            // 分段写入
            int current = 1;
            List<T> data = this.excelExportHandler.getData(current);
            while (data != null && data.size() > 0) {
                excelWriter.write(data, writeSheet);
                data = this.excelExportHandler.getData(++current);
            }
        }
        return EXPORT_PATH + fileName;
    }

    /**
     * 导出，大数据量写入不推荐使用
     *
     * @param fileName
     * @param sheetName
     * @param data
     * @return
     */
    public String exportExcel(String fileName, String sheetName, List<T> data) {
        EasyExcel.write(EXPORT_PATH + fileName, this.clazz).sheet(sheetName).doWrite(data);
        return EXPORT_PATH + fileName;
    }
}
